home *** CD-ROM | disk | FTP | other *** search
- UNIT common;
- {*******************************************************************************
- * *
- * PCMFAT 1.1/READBOOT 1.1 Common routines *
- * Copyright (c) 1991 Barry Simon *
- * *
- * First Published in PC Magazine, September 10, 1991 *
- * *
- * Requires Turbo Pascal 6.0 to compile (because of use of inline assembler) *
- * *
- *******************************************************************************}
- {$A-}
-
- INTERFACE
- USES DOS;
-
- TYPE
- STR2 = STRING[2];
- STR4 = STRING[4];
- BootSectorType = RECORD
- unused : ARRAY[0..1] OF Byte;
- SystemID : STRING[8];
- {we'll have to cheat to adjust the length
- byte offset 2 is actually not used}
- BytesPerSector : Word; {offset 11,12}
- SectorsPerCluster : Byte; {offset 13}
- SectorsBeforeData : Word; {offset 14,15}
- NumFAT : Byte; {offset 16}
- NumRootDir, {offset 17,18}
- NumSectors : Word; {offset 19,20}
- MediaDesc : Byte; {offset 21}
- NumSecPerFAT, {offset 22,23}
- NumSecPerTrack, {offset 24,25}
- NumHeads : Word; {offset 26,27}
- NumHidden, {offset 28-31}
- LongNumSec : LongInt; {offset 32-35}
- END;
-
- FUNCTION Hex(B : Byte) : STR2;
- FUNCTION HexWord(W : Word) : STR4;
- PROCEDURE ReadSector(SecNum : LongInt);
-
- CONST
- Use3NibbleFAT : Boolean = False;
- {If there is a 3NibbleFAT, it is simplest to read in three sectors
- of FAT at a time}
-
- VAR
-
- PBlock : RECORD {needed for >32M disks under DOS 4/5}
- SecNum : LongInt;
- NumberToRead : Word;
- BufferAddress : Pointer;
- END;
- Sector : ARRAY[0..8191] OF Byte; {512 needed in most cases; 8191
- for safety in non-standard setups}
- DriveNum : Byte; {0=A;1=B; etc}
- BootSector : BootSectorType ABSOLUTE Sector;
-
-
- IMPLEMENTATION
- CONST
- HexDigits : ARRAY[0..15] OF Char = '0123456789ABCDEF';
-
- FUNCTION Hex(B : Byte) : STR2; {Changes byte to hex string}
- BEGIN
- Hex := HexDigits[B DIV 16]+HexDigits[B MOD 16];
- END;
-
- FUNCTION HexWord(W : Word) : STR4; {only used in PCMFAT}
- BEGIN
- HexWord := Hex(Hi(W))+Hex(Lo(W));
- END;
-
- PROCEDURE ReadSector(SecNum : LongInt);
- VAR
- NeedPBlock, ErrorOccurred : Boolean;
- {DOS 4.0 introduced an extended call to Int 25/26H; this was needed
- for partitions over 32M. It works with any drive so we always
- use the extended call if DOS VER 4.0 or higher; this program will
- not run as it stands with Compaq DOS 3.31 and larger than 32M
- partitions}
- BufferSeg, BufferOfs : Word;
- FlagOut, ErrorOut, CXin, DXin : Word;
- BEGIN
- NeedPBlock := (Lo(DosVersion) > 3);
- PBlock.SecNum := SecNum;
- IF Use3NibbleFAT THEN PBlock.NumberToRead := 3 ELSE
- PBlock.NumberToRead := 1; {# sectors}
- PBlock.BufferAddress := @Sector;
- IF NeedPBlock THEN BEGIN
- BufferSeg := Seg(PBlock);
- BufferOfs := Ofs(PBlock);
- END ELSE BEGIN
- BufferSeg := Seg(Sector);
- BufferOfs := Ofs(Sector);
- END;
- IF NeedPBlock THEN CXin := $FFFF ELSE
- IF Use3NibbleFAT THEN CXin := 3 ELSE CXin := 1;
- IF NeedPBlock THEN DXin := 0 ELSE DXin := Word(SecNum);
- {Sec Num must be a word under DOS < 4}
- asm
- push ax
- push bx
- push cx
- push dx
- push bp
- push si
- push di
- push es
- push ds
- mov al, DriveNum
- mov ah, 0
- mov cx, CXin
- mov dx, DXin
- mov ds, BufferSeg
- mov bx, BufferOfs
- Int 25H
- pushf
- pop bx
- popf {restores original flags and stack}
- pop ds
- pop es
- pop di
- pop si
- pop bp
- pop dx
- pop cx
- mov FlagOut, bx
- mov ErrorOut, ax
- pop bx
- pop ax
- END; {inline assembler statements}
- ErrorOccurred := (FlagOut AND FCarry <> 0);
- IF ErrorOccurred THEN BEGIN
- WriteLn(' Fatal Error reading sector; program halted.');
- WriteLn(' Error Number ', HexWord(ErrorOut));
- Halt;
- END;
- END;
-
- END.
-